package de.hs.rm.UJAdapter.impl;

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.Map.Entry;

import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.TabularDataSupport;

import de.hs.rm.UJAdapter.util.ClassTypeUtil;

public class UJActionOpenType extends UJAction {
	
	protected boolean activated = true;
	protected boolean returnOpenType = false;

	public boolean isReturnOpenType() {
		return returnOpenType;
	}

	public void setReturnOpenType(boolean returnOpenType) {
		this.returnOpenType = returnOpenType;
	}

	public boolean isActivated() {
		return activated;
	}
	
	public void setActivated(boolean activated) {
		this.activated = activated;
	}

	@Override
	public Dictionary invoke(Dictionary args) throws Exception {
		Dictionary returnValue = null;
		if(activated)
		{
			Object result = null;
			if(inputArgumentsNames.length > 0)
			{
				Object[] params = new Object[inputArgumentsNames.length];
				
				for (int i = 0; i < inputArgumentsNames.length; i++)
					params[i] = args.get(inputArgumentsNames[i]);
				
				result = mBeanServerConnection.invoke(objName,
						this.getJavaName(),
						params,
						inputArgumentsTypes);
			}
			else
			{
				result = mBeanServerConnection.invoke(objName,
						this.getJavaName(),
						null,
						null);
				
			}
			if(result != null)
			{
				returnValue = new Hashtable();
				if(!returnOpenType)
				{
					returnValue.put(outputArgumentsNames[0], result);
					return returnValue;
				}
				else
				{
					ArrayList<Object> oList = new ArrayList<Object>();
					
					fillObjectListfromComplexType(result, oList);
					
					for(int i = 0; i < outputArgumentsNames.length; i++)
						returnValue.put(outputArgumentsNames[i], oList.get(i));
				}
			}
			else
				return returnValue;			
		}
		return returnValue;
	}
	
	private void fillObjectListfromComplexType(Object openData, ArrayList<Object> oList)
	{
		//recursively add simple type state variables from complex types
		switch(ClassTypeUtil.getOpenData(openData))
		{
			case ClassTypeUtil.OPENDATA_COMPOSITE:
				CompositeDataSupport cOpenData = 
					(CompositeDataSupport) openData;
				CompositeType cType = cOpenData.getCompositeType();
				Set<String> cKeys = cType.keySet();
				Iterator<String> cIt = cKeys.iterator();
				while(cIt.hasNext())
				{
					String key = cIt.next();
					fillObjectListfromComplexType(cOpenData.get(key), oList);
				}
			break;
			
			case ClassTypeUtil.OPENDATA_ARRAY:
				Object[] aOpenData = (Object[]) openData;
				for (int i = 0; i < aOpenData.length; i++)
					fillObjectListfromComplexType(aOpenData[i], oList);
			break;
				
			case ClassTypeUtil.OPENDATA_TABULAR:
				TabularDataSupport tOpenData = 
					(TabularDataSupport) openData;
				
				Set<Entry<Object, Object>> tEntrySet=  tOpenData.entrySet();
				//Set<Object> tKeys = tOpenData.keySet();
				//Iterator<Object> kIt = tKeys.iterator();
				Iterator<Entry<Object, Object>> kIt = tEntrySet.iterator();
				while(kIt.hasNext())
				{
					Entry<Object, Object> entry = kIt.next();
					fillObjectListfromComplexType(entry.getValue(), oList);
					
				}
			break;
			
			case ClassTypeUtil.OPENDATA_SIMPLE:
				oList.add(openData);
			break;
		}
		
	}

}
